using System.Linq;
using FireStarter.Base;
using FireStarter.Base.BusinessObjectMerger;
using FireStarterModeller.BO;
using FireStarterModeller.Logic.MergeBusinessObjects;
using FireStarterModeller.Test.BO;
using NUnit.Framework;

namespace FireStarterModeller.Test.Logic.MergeBusinessObjects
{
    [TestFixture]
    public class TestMergeUIField
    {
        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            TestUtilsLogic.SetupFixture();
        }
        [SetUp]
        public virtual void SetupTest()
        {
            TestUtilsLogic.SetupTest();
        }
        //This currently works because the UIField is incorrectly modelled
        // as having a compositional relationship to UIParamenters.
        // This is wrong since other classes have compositional rels to UIParameters.
        // The problem is incorrect design UIField, GridField and FilterField should all 
        // inherit from a common base that has a compositional relationship to UIParameters.
        [Test]
        public void Test_MergeUIField_ShouldMergeUIParameters()
        {
            //---------------Set up test pack-------------------
            var uiFieldMerger = MergeableBORegistry.Instance.Resolve<UIField>();
            var fromUIField = TestUtilsUIField.GetFactory()
                    .WithMany(field => field.UIParameters)
                    .WithOutSingleRelationships()
                    .CreateValidBusinessObject();

            var toUIField = new UIField();
            //---------------Assert Precondition----------------
            Assert.Greater(fromUIField.UIParameters.Count, 2);
            Assert.AreEqual(0, toUIField.UIParameters.Count);
            //---------------Execute Test ----------------------
            uiFieldMerger.MergeBOFrom(fromUIField, toUIField);
            //---------------Test Result -----------------------
            Assert.AreEqual(fromUIField.UIParameters.Count, toUIField.UIParameters.Count);
            Assert.AreEqual(3, toUIField.UIParameters.Count);
        }

        [Test]
        public void Test_MergeUIField_WhenTwoUpdatedParameters_ShouldUpdateParams()
        {
            //---------------Set up test pack-------------------
            var uiFieldMerger = MergeableBORegistry.Instance.Resolve<UIField>();
            var fromUIField = TestUtilsUIField.GetFactory()
                    .WithTwo(field => field.UIParameters)
                    .WithOutSingleRelationships()
                    .CreateValidBusinessObject();


            var toUIField = new UIField();
            var uiParameters = fromUIField.UIParameters;
            var fromUIParam = uiParameters[0];
            var fromUIParam2 = uiParameters[1];
            UIParameter expectedToUIParam = AddCopiedUIParam(toUIField, fromUIParam);
            UIParameter expectedToUIParam2 = AddCopiedUIParam(toUIField, fromUIParam2);

            //---------------Assert Precondition----------------
            Assert.AreEqual(2, fromUIField.UIParameters.Count);
            Assert.AreNotEqual(fromUIParam.Value, expectedToUIParam.Value);
            Assert.AreNotEqual(fromUIParam2.Value, expectedToUIParam2.Value);
            //---------------Execute Test ----------------------
            uiFieldMerger.MergeBOFrom(fromUIField, toUIField);
            //---------------Test Result -----------------------
            Assert.IsNotNull(toUIField);
            Assert.AreEqual(2, toUIField.UIParameters.Count);
            var toUIParam = toUIField.UIParameters.First();
          //  Assert.AreSame(expectedToUIParam, toUIParam);
            Assert.AreEqual(fromUIParam.Name, toUIParam.Name);
            Assert.AreEqual(fromUIParam.Value, toUIParam.Value);
            var toUIParam2 = toUIField.UIParameters.Last();
         //   Assert.AreSame(expectedToUIParam2, toUIParam2);
            Assert.AreEqual(fromUIParam2.Name, toUIParam2.Name);
            Assert.AreEqual(fromUIParam2.Value, toUIParam2.Value);
        }


        private static UIParameter AddCopiedUIParam(UIField toUIField, UIParameter fromUIParam)
        {
            var expectedToUIParam = new UIParameter {Name = fromUIParam.Name };
            toUIField.UIParameters.Add(expectedToUIParam);
            return expectedToUIParam;
        }

        private static UIParameter CreateUIParam(UIField  uiField)
        {
            var UIParameter = uiField.UIParameters.CreateBusinessObject();
            UIParameter.Name = TestUtilsShared.GetRandomString();
            UIParameter.Value = TestUtilsShared.GetRandomString();
            return UIParameter;
        }

        [Test]
        public void Test_MergeUIField_WhenOneRemovedParameters_ShouldUpdateParamsStatusToDelete()
        {
            //---------------Set up test pack-------------------
            var uiFieldMerger = MergeableBORegistry.Instance.Resolve<UIField>();
            var fromUIField = new UIField();
            var fromUIParam = CreateUIParam(fromUIField);
            var fromUIParam2 = CreateUIParam(fromUIField);
            var toUIField = new UIField();
            UIParameter expectedToUIParam = AddCopiedUIParam(toUIField, fromUIParam);
            UIParameter expectedToUIParam2 = AddCopiedUIParam(toUIField, fromUIParam2);
            fromUIField.UIParameters.Remove(fromUIParam2);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, fromUIField.UIParameters.Count);
            Assert.AreEqual(2, toUIField.UIParameters.Count);
            Assert.AreNotEqual(fromUIParam.Value, expectedToUIParam.Value);
            Assert.AreNotEqual(ChangeType.Update, expectedToUIParam.PendingChangeType);
            Assert.AreNotEqual(ChangeType.Delete, expectedToUIParam2.PendingChangeType);
            //---------------Execute Test ----------------------
            uiFieldMerger.MergeBOFrom(fromUIField, toUIField);
            //---------------Test Result -----------------------
            Assert.IsNotNull(toUIField);
            Assert.AreEqual(2, toUIField.UIParameters.Count);
            var toUIParam = toUIField.UIParameters.First();
            Assert.AreSame(toUIParam, expectedToUIParam);
            var toUIParam2 = toUIField.UIParameters.Last();
            Assert.AreSame(toUIParam2, expectedToUIParam2);
            //Assert.AreEqual(ChangeType.Update, toUIParam.PendingChangeType);
            Assert.AreEqual(ChangeType.Delete, toUIParam2.PendingChangeType);
        }

        [Test]
        public void Test_MergeUIField_WhenMergeToNotNull_ShouldUpdateUIField()
        {
            //---------------Set up test pack-------------------
            IMergeBO<UIField> mergeBO = MergeableBORegistry.Instance.Resolve<UIField>();
            var fromUIField = TestUtilsUIField.GetFactory()
                    .WithMany(field => field.UIParameters)
                    .WithOutSingleRelationships()
                    .CreateValidBusinessObject();
            fromUIField.PropertyName = "SomeValue";
            var toUiField = new UIField();
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(fromUIField.PropertyName, toUiField.PropertyName);
            //---------------Execute Test ----------------------
            mergeBO.MergeBOFrom(fromUIField, toUiField);
            //---------------Test Result -----------------------
            Assert.AreEqual(fromUIField.PropertyName, toUiField.PropertyName);
        }
      

    }
}